/*
 * Copyright 2010 - 2011, The PLDesktop Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

/**
 * Information we keep for operators.
 */
struct demangle_operator_info {
	/**
	 * Mangled name.
	 */
	const char *code;
	/**
	 * Real name.
	 */
	const char *name;
	/**
	 * Length of real name.
	 */
	int len;
	/**
	 * Number of arguments.
	 */
	int args;
};

/**
 * How to print the value of a builtin type.
 */
enum d_builtin_type_print {
	/**
	 * Print as (type)val.
	 */
	D_PRINT_DEFAULT,
	/**
	 * Print as integer.
	 */
	D_PRINT_INT,
	/**
	 * Print as unsigned integer, with trailing "u".
	 */
	D_PRINT_UNSIGNED,
	/**
	 * Print as long, with trailing "l".
	 */
	D_PRINT_LONG,
	/**
	 * Print as unsigned long, with trailing "ul".
	 */
	D_PRINT_UNSIGNED_LONG,
	/**
	 * Print as long long, with trailing "ll".
	 */
	D_PRINT_LONG_LONG,
	/**
	 * Print as unsigned long long, with trailing "ull".
	 */
	D_PRINT_UNSIGNED_LONG_LONG,
	/**
	 * Print as bool.
	 */
	D_PRINT_BOOL,
	/**
	 * Print as float--put value in square brackets.
	 */
	D_PRINT_FLOAT,
	/**
	 * Print in usual way, but here to detect void.
	 */
	D_PRINT_VOID
};

/**
 * Information we keep for a builtin type.
 */
struct demangle_builtin_type_info {
	/**
	 * Type name.
	 */
	const char *name;
	/**
	 * Length of type name.
	 */
	int len;
	/**
	 * Type name when using Java.
	 */
	const char *java_name;
	/**
	 * Length of java name.
	 */
	int java_len;
	/**
	 * How to print a value of this type.
	 */
	enum d_builtin_type_print print;
};

/**
 * The information structure we pass around.
 */
struct d_info {
	/**
	 * The string we are demangling.
	 */
	const char *s;
	/**
	 * The end of the string we are demangling.
	 */
	const char *send;
	/**
	 * The options passed to the demangler.
	 */
	int options;
	/**
	 * The next character in the string to consider.
	 */
	const char *n;
	/**
	 * The array of components.
	 */
	struct demangle_component *comps;
	/**
	 * The index of the next available component.
	 */
	int next_comp;
	/**
	 * The number of available component structures.
	 */
	int num_comps;
	/**
	 * The array of substitutions.
	 */
	struct demangle_component **subs;
	/**
	 * The index of the next substitution.
	 */
	int next_sub;
	/**
	 * The number of available entries in the subs array.
	 */
	int num_subs;
	/**
	 * The number of substitutions which we actually made from the subs
	 * array, plus the number of template parameter references we
	 * saw.
	 */
	int did_subs;
	/**
	 * The last name we saw, for constructors and destructors.
	 */
	struct demangle_component *last_name;
	/**
	 * A running total of the length of large expansions from the
	 * mangled name to the demangled name, such as standard
	 * substitutions and builtin types.
	 */
	int expansion;
};

#define d_peek_char(di) (*((di)->n))
#define d_peek_next_char(di) ((di)->n[1])
#define d_advance(di, i) ((di)->n += (i))
#define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0)
#define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++))
#define d_str(di) ((di)->n)

#define D_BUILTIN_TYPE_COUNT (32)
